/* Copyright (c) 2022 渝州大数据实验室
 *
 * Lanius is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.yzbdl.lanius.orchestrate.serv.utils;

import org.springframework.util.CollectionUtils;
import org.yzbdl.lanius.orchestrate.common.base.dto.TreeNodeDetailDto;
import org.yzbdl.lanius.orchestrate.common.base.dto.TreeNodeDto;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 构建树工具
 *
 * @author zhuhongji@yzbdl.ac.cn
 * @date 2022-04-11 13:41
 */
public class TreeUtil {

	/**
	 * 根据输入树节点构建树
	 * @param treeNodes 节树点
	 * @param <T> 节点
	 * @return 树结构
	 */
	public static  <T extends TreeNodeDto> List<T> build(List<T> treeNodes){
		return treeNodes.stream().peek(treeNode -> treeNodes.stream().filter(n -> treeNode.getId().equals(n.getParentId())).forEach(treeNode::addTreeNode))
				.filter(var -> Objects.isNull(var.getParentId()))
				.collect(Collectors.toList());
	}

	/**
	 * 根据输入树节点构建树
	 * @param treeNodes 节树点
	 * @param root 根节点标识
	 * @param <T> 节点
	 * @param <D> 根节点
	 * @return 树结构
	 */
	public static  <T extends TreeNodeDto, D> List<T> buildByRoot(List<T> treeNodes, D root){
		return treeNodes.stream().peek(treeNode -> treeNodes.stream().filter(n -> treeNode.getId().equals(n.getParentId())).forEach(treeNode::addTreeNode))
				.filter(var -> root.equals(var.getParentId()))
				.collect(Collectors.toList());
	}


    /**
     * 递归构建带有树路径的节点
     * @param treeNodes 节点合集
     * @param root 根节点标识
     * @param <T> 节点
     * @param <D> 根节点
     * @return 树结构
     */
    public static <T extends TreeNodeDetailDto, D> List<T> buildDetailByRoot(List<T> treeNodes, D root) {
        return treeNodes.stream().filter(n -> root.equals(n.getParentId())).peek(node -> {
            node.setPath("/" + node.getNodeName());
            buildTreeChildren(treeNodes, node);
        }).collect(Collectors.toList());
    }

    /**
     * 构建子节点
     * @param treeNodes 节点合集
     * @param parent 父节点
     * @param <T> 节点
     */
    private static <T extends TreeNodeDetailDto> void buildTreeChildren(List<T> treeNodes, TreeNodeDetailDto parent) {
        // 添加子节点
        treeNodes.stream().filter(n -> parent.getId().equals(n.getParentId())).forEach(node -> {
            node.setPath(parent.getPath() + "/" + node.getNodeName());
            parent.addTreeNode(node);
        });
        // 值节点递归调用
        if (!CollectionUtils.isEmpty(parent.getChildren())) {
            parent.getChildren().forEach(node -> buildTreeChildren(treeNodes, node));
        }
    }

}
